iT邦幫忙

2026 iThome 鐵人賽

DAY 29
1
佛心分享-IT 人技術創業

Berry AI:從零開始打造全美第一的得來速 Vision AI系列 第 29 篇

Berry AI 使用了哪些開源軟體?我們又回饋了什麼?

  • 分享至 

  • xImage
  •  

系列走到第 29 天,回顧前面幾篇的架構圖:反向代理、media server、BI 平台、監控管線,幾乎每一個方塊的背後都是開源專案。得來速 Vision AI 是高度垂直的題目,但把系統拆開來看,Berry AI 真正自己寫的是演算法與商業邏輯,其餘每一層都建立在開源軟體之上。

本篇盤點我們用了哪些開源軟體、分別用在哪裡,以及我們回饋了什麼。先說結論:用得很多,回饋得少。

門市端用了什麼

每一間店的 edge server,從作業系統到應用層都由開源軟體組成:

  • Ubuntu Server:edge server 的作業系統。搭配 autoinstall 完成全自動安裝,並以 LUKS 搭配 TPM 加密整個磁碟分割 (Day 05)。
  • Docker:門市內的服務全部以容器部署,image 在出貨前就預載進機器 (Day 05)。
  • Ansible 與 AWX:上千台 edge server 的組態管理與批次更新。Ansible 的 playbook 定義變更內容,AWX 管理排程、權限與執行紀錄。
  • rathole:反向代理 tunnel。edge server 藏在客戶內網的 NAT 後面,由它主動連回公司機房建立隧道,工程師才能連上散布全美的機器 (Day 06)。
  • Caddy:公司機房對外的唯一入口,負責 TLS 終止與流量轉發 (Day 06)。
  • MediaMTX:門市內的 media server。對 IP cam 只維持一條 RTSP 連線,往下游以 RTSP、HLS、WebRTC 分送給 Vision AI 與 Web 後台,同時錄影存檔 (Day 07)。
  • ffmpeg:影像轉碼與封裝轉換,把攝影機輸出的 codec 轉換成下游能播放的格式 (Day 07)。
  • PyTorch:Vision AI 模型的訓練框架,部署時匯出成 ONNX (跨框架的模型交換格式),在 edge server 上由 ONNX Runtime 推理。
  • OpenCV:影像處理,Day 09 到 Day 17 談的偵測、追蹤與校正都建立在它與 PyTorch 的生態系上。

雲端與資料端用了什麼

  • Apache Superset:BI 平台,承載內外部的資料儀表板 (Day 20)。
  • Redis:Superset 前面的快取層 (Day 27)。
  • Dagster 與 Celery:資料管線的編排與背景任務佇列。
  • dbt:資料倉儲內的 SQL 轉換層,報表背後的資料模型有版本、可測試 (Day 21)。
  • Grafana Alloy、Mimir、Loki:metrics 與 logs 的收集與儲存,整套建立在 Prometheus 生態系之上 (Day 27)。
  • Gatus:自架的健康檢查與狀態頁,持續驗證各項服務的可用性。
  • Playwright:壓力測試時模擬真實使用者操作瀏覽器 (Day 27)。
  • FastAPI 與 Django:後端服務的兩套框架,API 服務用 FastAPI,表單與後台密集的系統用 Django。
  • React:Web 前端。
  • Streamlit:內部工具的介面,例如 Day 15 的演算法調校平台。

這張清單並不完整。每一項的相依套件再往下展開還有好幾層,這裡只列出各層最主要的元件。

我們怎麼選開源軟體?

GitHub 的星星數是最先看到的指標,卻幾乎不影響我們的決策。回顧系列裡的幾次選型,真正影響結論的是這三件事:

  1. 需求契合:Day 06 選隧道方案時,frp 的星星數遙遙領先,但它的驗證 token 預設全域共用、port 又由客戶端決定,兩項都與我們的管理需求相反。
  2. 維護活躍度:同一輪評估裡的 nps,功能上符合需求,但最後一次更新停在兩年多前,累積五百多個 issue 無人處理。選了它,未來每一個 bug 都得自己修,等於從一開始就接下維護 fork 的成本。
  3. 營運成本:MediaMTX 是單一執行檔加一份 YAML,Caddy 與 rathole 也一樣。要部署進上千間門市、又只能遠端維護的環境,依賴越少的軟體,故障點就越少。

這三項指向同一個問題:這個專案能維持多久,以及出問題時我們有沒有能力自己修。

我們回饋了什麼?

我們的貢獻集中在一種模式上:在正式環境遇到問題,查出原因、修正、驗證,再送回上游。以我自己送出的 PR (pull request) 為例:

  • superset#24497:把官方 Docker image 底層的 Debian base image 釘住版本。上游 base image 的隱性更新曾讓同一份 Dockerfile 建出不同的結果,釘住版本後建置結果才可重現。另外還送出兩筆文件修正。
  • dagster#13800:修正 dagster-celery 一個設定選項前後不一致的問題。
  • readahead#19:Go 的串流預讀函式庫,Seek 之後回傳的位置不正確,會導致呼叫端從錯誤的位置讀取資料。
  • ssh_config#42:Python 的 SSH 設定檔解析器無法解析值裡帶 = 的 SetEnv,修正後我們的自動化工具才能處理所有實際存在的設定檔。
  • rathole#269:把非 root 使用者搭配 systemd 的部署方式寫成官方範例與說明,後來的使用者可以直接照做。
  • mediamtx#5166:錄影測試原本沒有驗證所有 track 都被錄下,H.265 的 track 漏錄也不會被測出,修正後這個測試才確實涵蓋每一條 track。

這些都談不上大功能,但每一筆都先在我們的環境裡驗證過才送出去:問題是真的,修法是有效的。對上游來說,一筆附上原因分析與修法的 PR 比一個 issue 有用得多;對我們來說,改動進了上游,之後升級就不需要維護本地的 patch。

進不了上游的,就留在 fork 裡

有些改動與自身需求綁得太緊,上游沒有理由合併,只能自己維護 fork (複製一份自行維護的 repo):

  • mediamtx:我們的 AI 事件需要與錄影檔案精確對時,因此 fork 加上了「錄影時把每個分段的 NTP 時間戳額外輸出成 CSV」的功能。這個需求只有我們的產品有,不適合送回上游。
  • headscale:自架的 Tailscale 控制伺服器。fork 裡有一個 patch,把 policy 計算 peer-map (每個節點能看見哪些節點的對應表) 時的全配對掃描改成索引式建表。這類改動要到節點數放大之後才量得出差異,先在 fork 裡支撐我們的規模,後續再整理送上游。

小結

開源最好的地方是它不問你是誰,我們可以站在這些巨人的肩膀上面做產品,也可以在某個深夜查出一個 bug 之後,把修正推送回去,為社群貢獻一份心力。這個系列寫下來的每一套系統,都是許多我們素未謀面的人一起建立起來的,他們把自己創意開源出來,讓更多人可以一同分享、回饋、貢獻,萬分感謝!


本系列由 Berry AI 工程團隊出品。更多工程實戰紀錄都在 Berry AI 技術部落格。


上一篇
人類和 AI Agent 都用得順手的 Python 開發環境:uv、ruff、ty 與 prek
系列文
Berry AI:從零開始打造全美第一的得來速 Vision AI 共 29 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言